#ifndef NASCCL_HashKey_Cpp
#define NASCCL_HashKey_Cpp
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
    The HashKey function will take any valid key and resize it to any size
    (between MaxKeyLength & MinKeyLength). This function will generate the same
    "Shorter or Longer" key every time it is called as long as the input key
    (InputKey) and the final key size (FinalSize) stay the same.

    This functions can also be used to remove Null, CR & LF from your keys.
*/
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include "NASCCL.H"
#include "sBoxes.H"
#include "Math.H"

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

bool HashKey(void *inUserKey, void *outHashKey, int inUserKeyLen, int inHashKeyLen)
{
    int LocalLoop = 0;
    int InKeyPos  = 0;
    int Box       = 0;

    NASCCLByte InKeyValue = 0;
    NASCCLByte sKeyValue  = 0;
    NASCCLByte sValue     = 0;
    NASCCLByte LastValue  = 0;
    NASCCLByte MValue1    = 0;
    NASCCLByte MValue2    = 0;

    if(inHashKeyLen > MaxKeyLength) return false;
    if(inHashKeyLen < MinKeyLength) return false;
    if(inUserKeyLen > MaxKeyLength) return false;
    if(inUserKeyLen < MinKeyLength) return false;
    if(outHashKey == 0) return false;
    if(inUserKey == 0)  return false;

    LastValue = ((NASCCLByte *)inUserKey)[InKeyPos];

    while(LocalLoop < inHashKeyLen)
    {
        InKeyValue = ((NASCCLByte *)inUserKey)[InKeyPos];
        sKeyValue  = sHashBox[Box][InKeyValue];
        sValue     = sHashBox[Box][LastValue];

        MValue1 = Merge( InKeyValue, sKeyValue, sValue, LastValue, InKeyPos, Box );
        MValue2 = Merge( Box, InKeyPos, LastValue, sValue, sKeyValue, InKeyValue );

        ((NASCCLByte *)outHashKey)[LocalLoop] =
            InKeyValue               + (
            (InKeyValue ^ MValue1)   +
            (InKeyValue ^ sKeyValue) +
            (InKeyValue ^ sValue)    +
            (InKeyValue ^ LocalLoop) +
            (InKeyValue ^ LocalLoop) +
            (InKeyValue ^ MValue2)   );

        if(((NASCCLByte *)outHashKey)[LocalLoop] == LastValue)
            (((NASCCLByte *)outHashKey)[LocalLoop] += Box);

        LastValue = ((NASCCLByte *)outHashKey)[LocalLoop];

        if(((NASCCLByte *)outHashKey)[LocalLoop] == 0 ) // Null
            ((NASCCLByte *)outHashKey)[LocalLoop] += 16;
        else if(((NASCCLByte *)outHashKey)[LocalLoop] == 10) // LF
            ((NASCCLByte *)outHashKey)[LocalLoop] += 24;
        else if(((NASCCLByte *)outHashKey)[LocalLoop] == 13) // CR
            ((NASCCLByte *)outHashKey)[LocalLoop] += 32;

        if(InKeyPos == inUserKeyLen)
            InKeyPos = -1;

        if(Box == BoxSize)
            Box = -1;

        LocalLoop++;
        InKeyPos++;
        Box++;
    }

    return true;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#endif

